#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Predesys - Predesys Bluetooth Proxy
# Version: 0.1.1
# Author: Jose A. Jimenez <jajimc@gmail.com>
# License: GPL 3.0 (see "license" file)

import sys
sys.dont_write_bytecode = True
import os.path
import exceptions
import simplexml

class BluetoothProxyConfiguration():
    """Class that represents the Predesys Bluetooth Proxy settings."""
    def __init__(self):
        """Class constructor.
        
        It initialize the object with the default values.
        """
        self.set_default_values()
        
    def set_default_values(self):
        """Set the default values to all fields.
        """
        self.set_bluetooth_channel(5)
        self.set_station_max_clients(2)
        self.set_bluetooth_buffer_size(1024)
        self.set_service_host("")
        self.set_service_port(80)
        self.set_tcpip_buffer_size(1024)
        
    def get_bluetooth_channel(self):
        return self.__bluetoothChannel
    
    def get_station_max_clients(self):
        return self.__stationMaxClients
    
    def get_bluetooth_buffer_size(self):
        return self.__bluetoothBufferSize
    
    def get_service_host(self):
        return self.__serviceHost
    
    def get_service_port(self):
        return self.__servicePort
    
    def get_tcpip_buffer_size(self):
        return self.__tcpipBufferSize
        
    def set_bluetooth_channel(self, value):
        """Sets the channel to use in bluetooth connections.
        
        Keyword arguments:
        value -- channel (integer)
        
        It raises an exception (ValueNotValidException) if value isn't an integer greater than or equal to 0. 
        """
        if value == None or type(value) != int or value < 0: raise ValueNotValidException("Bluetooth Channel must be a not null integer greater than or equal to 0.")
        self.__bluetoothChannel = value
    
    def set_station_max_clients(self, value):
        """Sets the maximum of clients that can connect to the proxy.
        
        Keyword arguments:
        value -- Maximum of clients (integer)
        
        It raises an exception (ValueNotValidException) if value isn't an integer greater than or equal to 1.         
        """    
        if value == None or type(value) != int or value < 1: raise ValueNotValidException("Station Maximum of Clients must be a not null integer greater than or equal to 1.")
        self.__stationMaxClients = value
    
    def set_bluetooth_buffer_size(self, value):
        """Sets the buffer size used to send and receive data in bluetooth connections.
        
        Keyword arguments:
        value -- Buffer size [KB] (integer)
        
        It raises an exception (ValueNotValidException) if value isn't an integer greater than or equal to 1.         
        """
        if value == None or type(value) != int or value < 1: raise ValueNotValidException("Bluetooth Buffer Size must be a not null integer greater than or equal to 1.")
        self.__bluetoothBufferSize = value
    
    def set_service_host(self, value):
        """Sets the service host to connect from clients.
        
        Keyword arguments:
        value -- Service host (HTTP host) (string)
        
        It raises an exception (ValueNotValidException) if value isn't a not null string.         
        """
        if value == None or type(value) != str: raise ValueNotValidException("Service Host must be a not null string.")
        self.__serviceHost = value
    
    def set_service_port(self, value):
        """Sets the port to use in bluetooth connections.
        
        Keyword arguments:
        value -- port (integer)
        
        It raises an exception (ValueNotValidException) if value isn't an integer greater than or equal to 0. 
        """
        if value == None or type(value) != int or value < 0: raise ValueNotValidException("Service Port must be a not null integer greater than or equal to 0.")
        self.__servicePort = value
    
    def set_tcpip_buffer_size(self, value):
        """Sets the buffer size used to send and receive data in TCP/IP connections.
        
        Keyword arguments:
        value -- Buffer size [KB] (integer)
        
        It raises an exception (ValueNotValidException) if value isn't an integer greater than or equal to 1.         
        """
        if value == None or type(value) != int: raise ValueNotValidException("TCP/IP Buffer Size must be a not null integer greater than or equal to 1.")
        self.__tcpipBufferSize = value

    def load_from_file(self, path):
        """Loads settings from a XML file.
        
        Keyword arguments:
        path -- File path to load (string)
        
        It raises an exception (ValueNotValidException) if path isn't a valid file path.
        It raises an exception (FileNotFoundException) if file doesn't exist.
        It raises an exception (LoadFileException) if an error occurs loading the file.
        """
        if path == None or type(path) != str or path == "": raise ValueNotValidException("Path must be a valid file path.")
        if not (os.path.exists(path) and os.path.isfile(path)): raise FileNotFoundException("Configuration file doesn't exist.")
          
        try:
            document = simplexml.SimpleXmlDocument(self.path)          
            self.set_bluetooth_channel(int(document.get_text_node_value("bluetoothChannel", 0)))
            self.set_station_max_clients(int(document.get_text_node_value("stationMaxClients", 0)))
            self.set_bluetooth_buffer_size(int(document.get_text_node_value("bluetoothBufferSize", 0)))
            self.set_service_host(document.get_text_node_value("serviceHost", 0))
            self.set_service_port(int(document.get_text_node_value("servicePort", 0)))
            self.set_tcpip_buffer_size(int(document.get_text_node_value("tcpipBufferSize",0)))
        except:
            raise LoadFileException("Configuration load error.")
            
    def save_to_file(self, path):
        """Saves settings to a file.
        
        Keyword arguments:
        path -- File path to save (string)
        
        It raises an exception (ValueNotValidException) if path isn't a valid file path.
        It raises an exception (SaveFileException) if an error occurs saving the file.
        """
        if path == None or type(path) != str or path == "": raise ValueNotValidException("Path must be a valid file path.")
        
        content = "<?xml version=\"1.0\" ?>\n"
        content += "<configuration>\n"
        content += "\t<bluetoothChannel>%d</bluetoothChannel>\n" % self.__bluetoothChannel
        content += "\t<stationMaxClients>%d</stationMaxClients>\n" % self.__stationMaxClients
        content += "\t<bluetoothBufferSize>%d</bluetoothBufferSize>\n" % self.__bluetoothBufferSize
        content += "\t<serviceHost>%s</serviceHost>\n" % self.__serviceHost
        content += "\t<servicePort>%d</servicePort>\n" % self.__servicePort
        content += "\t<tcpipBufferSize>%d</tcpipBufferSize>\n" % self.__tcpipBufferSize
        content += "</configuration>"
        
        try:
            with open(path, "w") as configFile:
                configFile.write(content)
        except:
            raise SaveFileException("Configuration save error.")
        
class ValueNotValidException(exceptions.Exception):
    pass

class FileNotFoundException(exceptions.Exception):
    pass

class LoadFileException(exceptions.Exception):
    pass
    
class SaveFileException(exceptions.Exception):
    pass
